home *** CD-ROM | disk | FTP | other *** search
- ; CPSPK1.ASM
- ; KERMIT - (Celtic for "FREE")
- ;
- ; This is the CP/M-80 implementation of the Columbia University
- ; KERMIT file transfer protocol.
- ;
- ; Version 4.0
- ;
- ; Copyright June 1981,1982,1983,1984
- ; Columbia University
- ;
- ; Originally written by Bill Catchings of the Columbia University Center for
- ; Computing Activities, 612 W. 115th St., New York, NY 10025.
- ;
- ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
- ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
- ; others.
- ;
- ; This file contains the (system-independent) routines that implement
- ; the KERMIT protocol, and the commands that use them:
- ; RECEIVE, SEND, FINISH, and LOGOUT.
- ;
- ; revision history:
- ;
- ;edit 23, 16-Jan-1991 by MF. The bug of (22) was not fixed (although
- ; the error described needed to be corrected). Really fixed the bug this:
- ; time. changed "lda 'E'" after "ptch9b" to "mvi a,'E'" -- Zilog
- ; mnemonic thinking must've addled my brain!
- ;edit 22, 14-Jan-1991 by MF. Fix bug in the code which sends an "E" packet
- ; to the remote Kermit on encountering "disk full" so that
- ; uncontrollified <CR><LF> is not copied to the packet data area (and
- ; hence sent to the remote Kermit). This should fix a bug reported
- ; by Russell Lang of Monash University in Australia wherein a PC
- ; running Kermit in Server mode complained of invalid characters when
- ; receiving the "disk full" error packet from CP/M Kermit.
- ;edit 21 of 3-Jan-1991 by MF. Reverse part of edit 20 which flushes comm
- ; input at EOF send: the problem of multiple copies of packets being
- ; sent when a stream of files being sent is partially interrupted with
- ; ^X has been fixed by modifying "inchr" in CPSPK2.ASM.
- ;edit 20, 2-Jan-1991 by MF. Tightened up code just after "sdata1" and around
- ; "sdat14". Added code to flush comm input after user has typed ^X
- ; or ^Z to interrupt file sends so that duplicate packets are not
- ; sent after the interrupt character (especially ^X) has been typed.
- ;edit 19, 14-Dec-1990 by MF. Place "<<>>" around "F" and "X" packets coming
- ; as replies to REMOTE commands a la VMS Bliss Kermit.
- ; Also type each character of "X" or "F" packet explicitly in case
- ; dollar-signs are part of the filename (as in VMS Bliss Kermit
- ; when a REMOTE TYPE is given and SET FILE NAMING FULL is in effect).
- ; Expanded code is at label rfil3f.
- ;edit 18, 27-Nov-1990 by MF. Fix bug introduced with edit 17 which resulted
- ; in "E" packet being sent twice when receiving file(s) and disk-full
- ; occurred. Sorry about that, folks!
- ;edit 17, 27-Nov-1990 by MF. When receiving files, make the decision as to
- ; whether to delete a partially-received file on a "disk full"
- ; condition subject to the setting of the SET INCOMPLETE-FILES
- ; switch in conformity with the behavior of MSDOS Kermit.
- ; An "E" packet is still sent to the remote Kermit. Also try to close
- ; any incomplete file whether deleting it or not (labels rdat16 and
- ; rdat3a). If keeping incomplete files, try to write outstanding
- ; buffers to disk, giving an error if the disk is full.
- ;edit 16, 23-Nov-1990 by MF. When receiving, cause the file being written
- ; to disk to **always** be deleted and an "E" packet to be sent when a
- ; "disk full" condition is encountered (per suggestion of
- ; RJL@MONU1.CC.MONASH.EDU.AU).
- ;edit 15, 15-Nov-1990 by MF. Changed code for the Receive Complete state
- ; to always go into RECEIVE if AUTORECEIVE is on. This will happen
- ; most of the time anyway as most mainframe Kermits issue a prompt
- ; after a single SEND command (wild-carded or not), thus guaranteeing
- ; that the modem status check of Kermit-80 ver. 4.09 would **always**
- ; have characters ready for input (the mainframe Kermit's prompt),
- ; defeating the status check and the Console input check (originally
- ; intended to drop the user out of the loop if he/she typed a key with
- ; no comm input present). Eliminate "any key" message there also.
- ; the user can drop out by hitting ^C.
- ; Of course, none of the foregoing applies if the Receive Complete
- ; state occurs as the result of a "Get" command where Autoreceive
- ; is meaningless and we just drop back to Kermit command-level.
- ;edit 14, 1-Oct-1990 by MF. Added code to send an "I" packet before an
- ; "R" packet in GET command.
- ; Modified routine "sinit" to ignore "E" packets when sending an
- ; "i" packet (per KPROTO.DOC).
- ;edit 13, 14-Sep-1990 by MF. Added code to implement SET FILE COLLISION
- ; and SET INCOMPLETE commands.
- ;edit 12, 9-Sep-1990 by MF. Added code to prevent packet counts
- ; from being displayed during Remote commands. Fixed
- ; AUTORECEIVE code, file colision Rename algorithm and eliminated
- ; multiple display of initial messages during GET/RECEIVE.
- ; edit 11, 28 July, 1987 by OBSchou. Commented out capas etc support
- ; (Long packets etc) as this is not worth the effort coding... but
- ; I have left what WAS done for any enthusiast. Also set in a few
- ; to NOT write to screen if SET TERMINAL QUIET set. Hopefully speeds
- ; up transfers on systems taking forever to update screens.
- ;
- ; edit 10, 8 April, 1987 by OBSchou. Tarted up all sorts of bits n bobs
- ; to cope with all the new aditions for Kermit-80 V 4.09
- ; Look for the [10] for most cahnges. spar and rpar largely replaced
- ;
- ; edit 9, March 30th by OBSchou. Set bits for automatically receiving
- ; another file if a remote sender sends files in seperate sessions.
- ; The code simply checks the serial line, and if there is some
- ; activity, assume its another SEND INIT packet. As there is no
- ; simple way to go to receive with the control-a, just ignore the
- ; packet. Causes one retry on the sender, but so what. Really
- ; should make it a server gizzmo.
- ;
- ; edit 8: January 28, 1987 by OBSchou
- ; Two major issues: firstly split CPSPKT.ASM into CPSPK(1 2).ASM
- ; making it far easier to handle this file.
- ; Second, some mode to the GET routines to correctly print the file
- ; name instead of the fireworks. Trouble was with GET <file> <file>
- ; and RECEIVE <file>. However, new bugs discovered...
- ;
- ; edit 7: August 11, 1986 Godfrey N. Nix [gnn] Nottingham University
- ; To ignore echoed packets (ie send 'S' receive 'S' before 'A');
- ; To allow character other than SOH for packet header (see also
- ; updates to CP4MIT and CP4UTL for other code needed);
- ; To permit SEND and RECEIVE to specify a host filename which
- ; is of a different structure to that of CP/M.
- ;
- ; edit 6a: [OBSchou] 7 March, 1985.
- ; Edited file with additions from MJ Carter. He writes:
- ; 25th September 1985, M J Carter [majoc], Nottingham University
- ; Code in gofil() amended, for exactly the same reasons to the
- ; alteration to cmifil() in cpscmd.asm. If there is any deep
- ; reason why gofil() has to be used instead of a call to comnd(cmofil),
- ; I can't see it. The bug (on a British Micro Mimi 803) caused
- ; gofil() to overwrite existing files in GET and RECEIVE, even
- ; with file warning SET ON.
- ;
- ;edir 6: November 22, 1984
- ; Change SEND's 'Unable to find file' error exit from calling
- ; error3 to calling prtstr instead. I don't know about you, but
- ; I greatly dislike having messages dumped into pre-existing
- ; junk on the screen where I have to spend lots of time hunting
- ; for them. [Hal Hostetler]
- ;
- ; edit 5: September 9, 1984
- ; Call flsmdm in init to flush old input when starting transfers.
- ; Select console before returning from inpkt.
- ; Replace inline code with calls to makfil/clofil to set up for
- ; multisector buffering on output.
- ; Remove superfluous call to clrlin in error3.
- ;
- ; edit 4: August 21, 1984 (CJC)
- ; Fix comment in inpkt: packet is terminated by NUL on return, not CR.
- ; If debugging, display the outgoing packet before putting the EOL
- ; character on, so the dumped packet doesn't get overwritten.
- ;
- ; edit 3: July 27, 1984
- ; add link directive for LASM. CP4PKT is linked by CP4MIT, and links
- ; to CP4TT. Add Toad Hall TACtrap to permit operations through a TAC.
- ;
- ; edit 2: June 8, 1984
- ; formatting and documentation; remove some unused labels; move setpar
- ; to cp4mit.m80; add module version string; make all arithmetic on
- ; 'pktnum' modulo 64; apply defaults correctly for missing parameters
- ; in send-init packet (and corresponding ack).
- ;
- ; edit 1: May, 1984
- ; extracted from CPMBASE.M80 version 3.9; modifications are described
- ; in the accompanying .UPD file.
- ;
- pk1ver: db 'CPSPK1.ASM (23) 16-Jan-1991$' ; name, edit number, date
-
- ; GET command [gnn]
- ; here from: kermit
-
- read: mvi a,0ffh ;[obs 8] we are doing a get
- sta getrxflg ;[obs 8] so set flag
- lxi d,remdat ;Where to put the text (if any.)
- mvi a,cmtxt
- call comnd ;Get either some text or a confirm.
- jmp kermt3 ; Didn't get anything.
- ora a ;Get any chars?
- jz kermt3 ;[gnn] GET must have a filename
- sta rdl ;Store the number of chars.
- xchg ;Get pointer into HL.
- mvi m,'$' ;Put in a dollar sign for printing.
- call init ;Clear the line and initialize the buffers.
- lda quietd ; quiet display?
- ana a
- jz read01 ;[MF]No, go ahead and position cursor
- call prcrlf ;[MF]Yes, keep from overwriting the prompt
- jmp read00 ;[MF]and write filename
- read01: call scrfln ;Position cursor [MF]
- read00: lxi d,remdat ;Print the file name, in either case
- call prtstr
- jmp read0a ;[gnn] go get local name if any
-
-
- ; enter here for RECEIVE command [gnn]
- read0: mvi a,0 ;[gnn]
- sta rdl ;[gnn][MF] flag entry as receive, not get
- sta getrxflg ;[obs 8] doing a receive, so reset flag
- call init ;clear line, initialise buffers
- read0a: lxi d,remnam ;[gnn] save local name here
- mvi a,cmtxt ;[gnn]
- call comnd ;[gnn] read second filename if present
- jmp kermt3 ;[gnn] error exit
- sta remlen ;[gnn] save length of name, may be zero
- sta getrxflg ;[obs 8] May also be receive <fnam> so
- ;[obs 8]pretend get for printing filename
- lda rdl ;[gnn] look at first name
- ora a ;[gnn] receive or get?
- jz read1 ;[gnn] receive
-
- mvi a,'I' ;[MF]Set state to send "I" packet
- sta state ;[MF]...
-
- ; jmp read12 ;[obs] [gnn] does not want this
-
- read1: ;call init ;Clear the line and initialize the buffers.
- read12: xra a
- sta czseen ;Clear the ^X/^Z flag initially.
- lxi h,0
- shld numpkt ;Set the number of packets to zero.
- shld numrtr ;Set the number of retries to zero.
- sta pktnum ;Set the packet number to zero.
- sta numtry ;Set the number of tries to zero.
- lda quietd ; quiet display?
- ana a
- jnz read13 ; yes, so dont write...
- call scrnrt ;Position cursor
- lxi h,0
- call nout ;Write the number of retries.
- read13: lda rdl ;[MF]Get or receive?
- ora a ;[MF]...
- jnz read2 ;[MF]Get, don't reset state
- mvi a,'R'
- sta state ;Set the state to receive initiate.
- ;...
- ;
- ;RECEIVE state table switcher.
-
- read2: lda quietd ; noisy display?
- ana a
- jnz read21 ; no, a quiet one
- lda remtxt ;[MF] In Remote command?
- ora a
- jnz read21 ;[MF] Yes, don't write to screen
- call scrnp ;Position cursor
- lhld numpkt
- call nout ;Write the current packet number.
- read21: lda state ;Get the state.
- cpi 'D' ;Are we in the DATA receive state?
- jnz read22
- call rdata
- jmp read2
-
- read22: cpi 'X' ; F packet but not an F packet?
- jnz read3 ; nope, so try next one
- call rfile ; 'get' the filename (but dont open it)
- jmp read2
-
- read3: cpi 'F' ;Are we in the FILE receive state?
- jnz read4
- call rfile ;Call receive file.
- jmp read2
-
- read4: cpi 'R' ;Are we in the Receive-Initiate state?
- jnz read5
- call rinit
- lda state ;[jd] get new state
- cpi 'F' ;[jd] went into receive state?
- jnz read2 ;[jd] no
- lxi d,inms24 ;[jd] yes, get receiving... message
- call finmes ;[jd] go print it
- jmp read2
-
- read5: cpi 'C' ;Are we in the Receive-Complete state?
- jnz read6
- lxi d,infms3 ;Put in "Complete" message.
- lda czseen ;Or was it interrupted?
- ora a ; . . .
- jz read5a ;No.
- xra a ;Yes, clear flag.
- sta czseen ; ...
- lxi d,inms13 ;Issue "interrupted" message.
- read5a: lda remtxt ;[MF] Doing a Remote command?
- ora a
- cz finmes ;Print completion message in right place if not
- ;
- lda rdl ;[MF]Receive or Get?
- ora a ;[MF]...
- jnz kermit ;[MF]Get, Autoreceive means nothing.
- lda autorc ; see if we want autoreceives
- ana a
- jz kermit ;[MF]No autoreceives, so drop out
- lxi d,autmes ;[MF]Yes, tell the user what we're doing
- call prtstr ;[MF]...
- jmp read1 ;[MF]Try another Receive (we get one
- ;[MF]retry from the sender as the ^A is lost)
-
- read6: cpi 'Y' ;[MF]Simple ack (from remote command)?
- jz kermit ;[MF]Yes
-
- cpi 'I' ;[MF]Exchanging parameters via info packet?
- jnz read7 ;[MF]No
- call sinit ;[MF]Yes, send the packet
- lda state ;[MF]Now see what happened
- cpi 'X' ;[MF]Did we exchange parameters successfully?
- jz read6a ;[MF]Yes, go send the filespec
- cpi 'A' ;[MF]No, are we in abort state?
- jnz read2 ;[MF]No, try again
- jmp kermit ;[MF]Yes, it's a real disaster, we must stop
- read6a: lda rdl ;[MF]Get length of filespec
- sta argblk+1 ;[MF]as length of packet
- mov c,a ;[MF]We must copy the filespec
- mvi b,0 ;[MF]...
- lxi h,remdat ;[MF]from the temporary buffer
- lxi d,data ;[MF]to the packet data area
- call mover ;[MF]Do it.
- ; for GET we must send the name of the file we want [gnn]
-
- mvi a,'1' ;Start with single character checksum
- sta curchk ;Save the type
- xra a ;Start a packet zero.
- sta argblk
- mvi a,'R' ;Receive init packet.
- call spack ;Send the packet.
- jmp kermt3 ; Die!
- xra a
- sta czseen ;Clear the ^X/^Z flag initially.
- lxi h,0
- shld numpkt ;Set the number of packets to zero.
- sta pktnum ;Set the packet number to zero.
- sta numtry ;Set the number of tries to zero.
- mvi a,'R' ;[MF]Set state to Receive-Initiate
- sta state ;[MF]...
- jmp read21 ;[MF]and go around again
- ;[MF]without retyping packet-number
-
- read7: cpi 'A' ;Are we in the Receive-"Abort" state?
- jnz read8
- read8: lxi d,infms4 ;Anything else is equivalent to "abort".
- call finmes
- jmp kermit
- ;
- ; Receive routines
-
- ; Receive init
- ; called by: read
-
- rinit: lda numtry ;Get the number of tries.
- cpi imxtry ;Have we reached the maximum number of tries?
- jm rinit2
- lxi d,ermes4
- call error3 ;Move cursor and print an error message.
- jmp abort ;Change the state to abort.
-
- rinit2: inr a ;Increment it.
- sta numtry ;Save the updated number of tries.
- mvi a,'1' ;Reset block check type to single character
- sta curchk ;Store as current type for initialization
- call rpack ;Get a packet.
- jmp nak ; Trashed packet: nak, retry.
- cpi 'S' ;Is it a send initiate packet?
- jnz rinit3 ;If not see if its an error.
- rini2a: lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- xra a
- sta numtry ;Reset the number of tries.
- lda argblk ;Returned packet number. (Synchronize them.)
- call countp
- lda argblk+1 ;Get the number of arguments received.
- lxi h,data ;Get a pointer to the data.
- call spar ;Get the data into the proper variables.
- lxi h,data ;Get a pointer to our data block.
- call rpar ;Set up the receive parameters.
- sta argblk+1 ;Store the returned number of arguments.
- mvi a,'Y' ;Acknowledge packet.
- call spack ;Send the packet.
- jmp abort ; Failed, abort.
- lda inichk ;Now switch to agreed upon check-type
- sta curchk ;For all future packets
- mvi a,'F' ;Set the state to file send.
- sta state
- ret
-
- rinit3: cpi 'E' ;Is it an error packet.
- jnz nak0 ;If not NAK whatever it is.
- call error
- jmp abort
- ;
- ; Receive file
- ; called by: read
-
- rfile: lda numtry ;Get the number of tries.
- cpi maxtry ;Have we reached the maximum number of tries?
- jm rfile1
- lxi d,ermes5
- call error3 ;Move cursor and print an error message.
- jmp abort ;Change the state to abort.
-
- rfile1: inr a ;Increment it.
- sta numtry ;Save the updated number of tries.
- call rpack ;Get a packet.
- jmp nak ; Trashed packet: nak, retry.
- cpi 'S' ;Is it a send initiate packet?
- jnz rfile2 ; No, try next type.
- lda oldtry ;Get the number of tries.
- cpi imxtry ;Have we reached the maximum number of tries?
- jm rfil12 ;If not proceed.
- lxi d,ermes4
- call error3 ;Move cursor and print an error message.
- jmp abort ;Change the state to abort.
-
- rfil12: inr a ;Increment it.
- sta oldtry ;Save the updated number of tries.
- lda pktnum ;Get the present packet number.
- dcr a ;Decrement
- ani 3FH ; modulo 64
- mov b,a
- lda argblk ;Get the packet's number
- cmp b ;Is the packet's number one less than now?
- jnz nak0 ;No, NAK and try again.
- call updrtr ;Update the retry count.
- xra a
- sta numtry ;Reset the number of tries.
- lxi h,data ;Get a pointer to our data block.
- call rpar ;Set up the parameter information.
- sta argblk+1 ;Save the number of arguments.
- mvi a,'Y' ;Acknowledge packet.
- call spack ;Send the packet.
- jmp abort ; Failed, abort.
- ret
-
- rfile2: cpi 'Z' ;Is it an EOF packet?
- jnz rfile3 ; No, try next type.
- lda oldtry ;Get the number of tries.
- cpi maxtry ;Have we reached the maximum number of tries?
- jm rfil21 ;If not proceed.
- lxi d,ermes6
- call error3 ;Move cursor and print an error message.
- jmp abort ;Change the state to abort.
-
- rfil21: call tryagn
- ret
-
- rfile3: cpi 'F' ;Start of file?
- jnz rfil3b
- mov c,a ;[MF]Save packet type
- lda remtxt ;[MF]Doing a remote server command?
- ora a ;[MF]...
- mov a,c ;[MF]Restore packet type
- jnz rfil3d ;[MF]If yes, same as x packet
- call compp
- jnz nak0 ;No, NAK it and try again.
- call countp
- mov c,a ;[MF]
- lda remtxt ;[MF]Doing a remote command?
- ora a ;[MF]...
- mov a,c ;[MF]
- jnz rfil3a ;[MF]Yes, don't open a file
- call gofil ;Get a file to write to, and init output buffer.
- jmp abort
- rfil3a: lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- call ackp
- mvi a,'D' ;Set the state to data receive.
- sta state
- lda czseen ;Check if we punted a file
- cpi 'Z' ;and didn't want any more
- rz ;If that was the request, keep telling other end
- xra a ;Otherwise, clear flag (^X is only for one file)
- sta czseen ;And store the flag back
- ret
-
- rfil3b: cpi 'X' ;Start of 'file?' , but not a file?
- jnz rfile4
- rfil3d: call compp
- jnz nak0 ;No, NAK it and try again.
- call countp
-
- call selcon ;[MF]Select Console
- lda argblk+1 ; get length
- ora a ;[MF]Anything to write?
- jz rfil3e ;[MF]No
- push psw ;[MF]Yes, save character count
- mvi e,'<' ;[MF]Write "<<" as in VMSKermit
- push d ;[MF]...
- call outcon ;[MF]...
- pop d ;[MF]...
- call outcon ;[MF]...
- pop psw ;[MF]Restore character count
- lxi h,data ; lets write the filename (?) to display
- rfil3f: push psw ;[MF]Save loop counter
- mov e,m ;[MF]Get character to write
- inx h ;[MF]and increment character pointer
- push h ;[MF]Save the pointer
- call outcon ;[MF]Write character to display
- pop h ;[MF]Restore pointer
- pop psw ;[MF]and loop counter
- dcr a ;[MF]Decrement the counter
- jnz rfil3f ;[MF]Display entire filename
- mvi e,'>' ;[MF]Put in ">>" as in VMSKermit
- push d ;[MF]...
- call outcon ;[MF]...
- pop d ;[MF]...
- call outcon ;[MF]...
- call prcrlf ;[MF]New line
- rfil3e: lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- call ackp
- mvi a,'D' ; expecting a D packet
- sta state
- lda czseen ;Check if we punted a file
- cpi 'Z' ;and didn't want any more
- rz ;If that was the request, keep telling other end
- xra a ;Otherwise, clear flag (^X is only for one file)
- sta czseen ;And store the flag back
- ret
-
- rfile4: cpi 'B' ;End of transmission.
- jnz rfile5
- call compp
- jnz nak0 ;No, NAK it and try again.
- xra a ;No data. (Packet number already in argblk).
- sta argblk+1
- mvi a,'Y' ;Acknowledge packet.
- call spack ;Send the packet.
- jmp abort
- mvi a,'C' ;Set the state to complete.
- sta state
- ret
-
- rfile5: cpi 'E' ;Is it an error packet.
- jnz abort
- call error
- jmp abort
- ;
- ; Receive data
- ; called by: read
-
- rdata: lda numtry ;Get the number of tries.
- cpi maxtry ;Have we reached the maximum number of tries?
- jm rdata1
- lxi d,erms10
- call error3 ;Display error message.
- rdat16: lda remtxt ;[MF]Is a Remote command in progress?
- ora a ;[MF]...
- jnz abort ;[MF]Yes, don't worry about file disposition
- lda incflg ;[MF]Are we keeping incomplete files?
- ora a ;[MF]...
- jnz rdat17 ;[MF]Yes
- lxi d,fcb ;[MF]No, close the file, ignoring errors
- push d ;[MF]while protecting the pointer
- mvi c,closf ;[MF]...
- call bdos ;[MF]...
- pop d ;[MF]Now delete the file, ignoring errors
- mvi c,delf ;[MF]...
- call bdos ;[MF]...
- jmp abort ;Change the state to abort.
- rdat17: call clofil ;[MF]Try to close the file, writing
- ;[MF]outstanding buffers to disk
- jmp rdat37 ;[MF]We can't, the disk is full
- jmp abort ;[MF]Change the state to "abort"
-
- rdata1: inr a ;Increment it.
- sta numtry ;Save the updated number of tries.
- call rpack ;Get a packet.
- jmp nak ; Trashed packet: nak, retry.
- cpi 'D' ;Is it a data packet?
- jnz rdata2 ; No, try next type.
- call compp ;check for correct packet number (zero flag = ok)
- jz rdat14 ;its correct
- lda oldtry ;Get the number of tries.
- cpi maxtry ;Have we reached the maximum number of tries?
- jm rdat12 ;If not proceed.
- lxi d,erms10
- call error3 ;Display err msg.
- jmp rdat16 ;[MF]Change the state to abort.
-
- rdat12: call tryagn
- ret
-
- rdat14: call countp
- lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- lda argblk+1 ;Get the length of the data.
- call ptchr
- jmp rdat3b ;[MF] Unable to write out chars;abort.
- xra a
- sta numtry ;Reset the number of tries.
- sta argblk+1 ;No data. (Packet number still in argblk.)
- mov c,a ;Assume no data
- lda czseen ;Check if control-X typed
- ora a ; . . .
- jz rdat15 ;Zero if not typed
- mov c,a ;Get the type of character typed
- mvi a,1 ;One data character
- sta argblk+1 ;Save the count
- mov a,c ;Get the possible data character
- sta data ;Store in data area
- rdat15: mvi a,'Y' ;Acknowledge packet.
- call spack ;Send the packet.
- jmp rdat16 ;[MF]
- ret
-
- rdata2: cpi 'F' ;Start of file?
- jnz rdata3 ; No, try next type.
- lda oldtry ;Get the number of tries.
- cpi maxtry ;Have we reached the maximum number of tries?
- jm rdat21 ;If not proceed.
- lxi d,ermes5
- call error3 ;Display err msg.
- jmp rdat16 ;[MF]Change the state to abort.
-
- rdat21: call tryagn
- ret
-
- rdata3: cpi 'Z' ;Is it a EOF packet?
- jnz rdata4 ;Try and see if its an error.
- call compp
- jnz nak0 ;No, NAK it and try again.
- call countp
- lda argblk+1 ;Get the data length
- cpi 1 ;Have one item?
- jnz rdat33 ;If not, ignore data
- lda data ;Yes, get the character
- cpi 'D' ;Is it a 'D' for discard?
- jz rdat36 ;If so, punt file
- rdat33: lda remtxt ;[MF]Writing text to disk?
- ora a ;[MF]...
- jnz rdat38 ;[MF]No, don't close file
- call clofil ;Finish off the file.
- jmp rdat37 ; Give up if the disk is full.
- rdat38: xra a ;Since we kept the file,
- sta czseen ;don't say it was discarded.
- lda numtry ;Get the number of tries. [MF]
- sta oldtry ;Save it. [MF]
- call ackp ;[MF]
- jmp rdat39 ;[MF]and get ready to get more files
- rdat36: lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- call ackp
- lda remtxt ;[MF]Is a Remote command in progress?
- ora a ;[MF]...
- jnz rdat39 ;[MF]Yes, don't worry about file disposition
- lda dscflg ;[MF]Is the file being punted because
- ora a ;[MF]of a collision?
- jnz rdat39 ;[MF]Yes, don't delete the existing file
- lda incflg ;[MF]No, are we keeping incomplete files?
- ora a ;[MF]...
- jnz rdat3a ;[MF]Yes
- lxi d,fcb ;[MF]No, close the file,
- mvi c,closf ;[MF]ignoring errors
- push d ;[MF]...
- call bdos ;[MF]...
- pop d ;[MF]Now delete the file,
- mvi c,delf ;[MF]ignoring errors
- call bdos ;[MF]...
- jmp rdat39 ;[MF]and continue
- rdat3a: call clofil ;[MF]Try to close the file, writing
- ;[MF]outstanding buffers to disk
- jmp rdat37 ;[MF]Can't, disk is full
- rdat39: mvi a,'F'
- sta state
- ret
-
- rdat37: call ptchr9 ; Send "?Disk full" on the error line [MF]
- ; and to the remote Kermit [MF]
- rdat3b: lda remtxt ;[MF]Doing a Remote command?
- ora a ;[MF]...
- jnz abort ;[MF]Yes, just abort
- lxi d,fcb ;[MF]Close the file, ignoring errors
- push d ;[MF]Protect fcb pointer
- mvi c,closf ;[MF]...
- call bdos ;[MF]...
- pop d ;[MF]Restore pointer
- lda incflg ;[MF]Are we keeping incomplete files?
- ora a ;[MF]...
- jnz abort ;[MF]Yes, just abort transfer
- mvi c,delf ;[MF]No, delete the file, ignoring errors
- call bdos ;[MF]...
- jmp abort ;[MF] abort transfer
-
- rdata4: cpi 'E' ;Is it an error packet.
- jnz rdat16 ;[MF]
- call error
- jmp rdat16 ;[MF]
- ;
- ; SEND command
- ; here from: kermit
-
- send: mvi a,cmifi ;Parse an input file spec.
- lxi d,fcb ;Give the address for the FCB.
- call comnd
- jmp kermit ; Give up on bad parse.
- ; section to get remote filename [gnn]
- lxi d,remnam ;[gnn] where to put filename
- mvi a,cmtxt ;[gnn]
- call comnd ;[gnn] get the text to end of the line
- jmp kermt3 ;[gnn] failure in reading buffer
- sta remlen ;[gnn] save length (may be zero)
- ;
- xra a
- sta mfflg1 ; clear flags...
- sta mfflg2
- sta mfflg3 ;[gnn]
- sta fcbcnt ;[gnn] clear fcbcount
- lxi h,fcb0 ;[gnn] and fcb pointer
- shld xfcbptr
- ;
- call mfname ;handle (multi) files
- jnc send14 ;got a valid file-name
- lxi d,erms15
- call prtstr ;Display error msg. ([hh] where it's visible)
- jmp kermit
-
- send14: call init ;Clear the line and initialize the buffers.
- xra a
- sta pktnum ;Set the packet number to zero.
- sta numtry ;Set the number of tries to zero.
- sta wrn8 ;[jd] we haven't sent the 8-bit-lost warning
- lxi h,0
- shld numpkt ;Set the number of packets to zero.
- shld numrtr ;Set the number of retries to zero.
- lda quietd ; a quiet display?
- ana a
- jnz send15 ; yup, dont write
- call scrnrt ;Position cursor
- lxi h,0
- call nout ;Write the number of retries.
- send15: mvi a,'1' ;Reset to use single character checksum
- sta curchk ;For startup
- mvi a,'S'
- sta state ;Set the state to receive initiate.
- ;...
- ;
- ;SEND state table switcher
-
- send2: lda quietd ; a quiet display?
- ana a
- jnz send21 ; yes, so dont write
- call scrnp ;Position cursor
- lhld numpkt
- call nout ;Write the packet number.
- send21: lda state ;Get the state.
- cpi 'D' ;Are we in the data send state?
- jnz send3
- call sdata
- jmp send2
-
- send3: cpi 'F' ;Are we in the file send state?
- jnz send4
- call sfile ;Call send file.
- jmp send2
-
- send4: cpi 'Z' ;Are we in the EOF state?
- jnz send5
- call seof
- jmp send2
-
- send5: cpi 'S' ;Are we in the send initiate state?
- jnz send6
- call sinit
- lda state ;[jd] get state back
- cpi 'F' ;[jd] into file send state yet?
- jnz send2 ;[jd] no
- lxi d,inms23 ;[jd] yes, print sending...
- call finmes ;[jd]
- jmp send2
-
- send6: cpi 'B' ;Are we in the eot state?
- jnz send7
- call seot
- jmp send2
-
- send7: cpi 'C' ;Are we in the send complete state?
- jnz send8 ;No...
- lxi d,infms3 ;Yes, write "Complete" message.
- lda czseen ;Or was it interrupted?
- ora a ; . . .
- jz send7a ;No.
- lxi d,inms13 ;Yes, then say "Interrupted" instead.
- send7a: call finmes
- jmp kermit
-
- send8: cpi 'A' ;Are we in the send "abort" state?
- jnz send9
- lxi d,infms4 ;Print message.
- call finmes
- jmp kermit
-
- send9: lxi d,infms4 ;Anything else is equivalent to "abort".
- call finmes
- jmp kermit
- ;
- ; Send routines
-
- ; Send initiate
- ; called by: send
-
- sinit: lda numtry ;Get the number of tries.
- cpi imxtry ;Have we reached the maximum number of tries?
- jm sinit2
- lxi d,erms14
- call error3 ;Display ermsg
- jmp abort ;Change the state to abort.
-
- sinit2: inr a ;Increment it.
- sta numtry ;Save the updated number of tries.
- mvi a,'1' ;Reset to use single character checksum
- sta curchk ;For startup
- lda chktyp ;Get our desired block check type
- sta inichk ;Store so we tell other end
- lxi h,data ;Get a pointer to our data block.
- call rpar ;Set up the parameter information.
- sta argblk+1 ;Save the number of arguments.
- lda numpkt ;Get the packet number.
- sta argblk
- lda state ; load state (I or S)
-
- call spack ;Send the packet.
- jmp abort ; Failed, abort.
- call rpack ;Get a packet.
- jmp r ; Trashed packet don't change state, retry.
- cpi 'Y' ;ACK?
- jnz sinit3 ;If not try next.
- call compp ;compare packets. If ok, zero flag set
- rnz ;If not try again.
- call countp ;increment packet number modulo 64
- lda argblk+1 ;Get the number of pieces of data.
- lxi h,data ;Pointer to the data.
- call spar ;Read in the data. (decode what they want)
- lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- xra a
- sta numtry ;Reset the number of tries.
- lda state ; se if S or I state
- cpi 'I' ; I state, so set X as next state
- jnz sinita
- sinitb: mvi a,'X'
- sta state
- ret
-
- sinita: lda inichk ;Get the agreed upon block check type
- sta curchk ;Store as type to use for packets now
- mvi a,'F' ;Set the state to file send. (Assumed)
- sta state
- call getfil ;Open the file.
- ret ; assume success; mfname thinks the file exists.
-
- sinit3: cpi 'N' ;NAK?
- jnz sinit4 ;If not see if its an error.
- call updrtr ;Update the number of retries.
- lda pktnum ;Get the present packet number.
- inr a ;Increment
- ani 3FH ; modulo 64
- mov b,a
- lda argblk ;Get the packet's number.
- cmp b ;Is the packet's number one more than now?
- rnz ;If not assume its for this packet, go again.
- xra a
- sta numtry ;Reset number of tries.
- mvi a,'F' ;Set the state to file send.
- sta state
- ret
-
- sinit4: cpi 'E' ;Is it an error packet.
- jnz abort
- lda state ;[MF]Get state
- cpi 'I' ;[MF]If an "I" packet was sent,
- jz sinitb ;[MF]Ignore the error, pretend success
- call error ;[MF]else display the error info
- jmp abort ;[MF]and abort
- ;
- ; Send file header
- ; called by: send
- ;[5a] Question [majoc]: Why could not the filename
- ; parsing have been done by comnd, like all the rest?
-
- sfile: lda numtry ;Get the number of tries.
- cpi maxtry ;Have we reached the maximum number of tries?
- jm sfile1
- lxi d,erms14
- call error3
- jmp abort ;Change the state to abort.
-
- sfile1: inr a ;Increment it.
- sta numtry ;Save the updated number of tries.
- xra a ;Clear A
- sta czseen ;No control-Z or X seen
- lxi h,data ;Get a pointer to our data block.
- shld datptr ;Save it.
- ; use remote name if given, else use local name [gnn]
- lda remlen ;[gnn] anything given?
- ora a ;[gnn]
- jnz sfile4 ;[gnn] use remote name
-
- lxi h,fcb+1 ;Pointer to the file name in the FCB.
- shld fcbptr ;Save position in FCB.
- mvi b,0 ;No chars yet.
- mvi c,0
- sfil11: mov a,b
- cpi 8H ;Is this the ninth char?
- jnz sfil12 ;If not proceed.
- mvi a,'.' ;Get a dot.
- lhld datptr
- mov m,a ;Put the char in the data packet.
- inx h
- shld datptr ;Save position in data packet.
- inr c
- sfil12: inr b ;Increment the count.
- mov a,b
- cpi 0CH ;Twelve?
- jp sfil13
- lhld fcbptr
- mov a,m
- ani 7fH ;Turn off CP/M 2 or 3's high bits.
- inx h
- shld fcbptr ;Save position in FCB.
- cpi '!' ;Is it a good character?
- jm sfil11 ;If not get the next.
- lhld datptr
- mov m,a ;Put the char in the data packet.
- inx h
- shld datptr ;Save position in data packet.
- inr c
- jmp sfil11 ;Get another.
-
- sfil13: mov a,c ;Number of char in file name.
- sta argblk+1
- lhld datptr
- mvi a,'$'
- mov m,a ;Put in a dollar sign for printing.
- lda quietd ; a quiet display
- ana a
- jnz sfi13a ; yes, dont write
- call scrfln ;Position cursor
- sfi13a: lxi d,data ;Print the file name though, in either case
- call prtstr
- lda pktnum ;Get the packet number.
- sta argblk
- mvi a,'F' ;File header packet.
- call spack ;Send the packet.
- jmp abort ; Failed, abort.
- call rpack ;Get a packet.
- jmp r ; Trashed packet don't change state, retry.
- cpi 'Y' ;ACK?
- jnz sfile2 ;If not try next.
- call compp
- rnz ;If not hold out for the right one.
- sfil14: call countp
- lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- xra a
- sta numtry ;Reset the number of tries.
- sta bytes ;[10] clear the "bytes transferred" counter
- sta bytes+1 ;[10]
- sta bytes+2 ;[10]
- sta bytes+3 ;[10]
- call gtchr ;Fill the first data packet
- jmp sfil16 ;Error go see if its EOF.
- ; ;Got the chars, proceed.
- sta size ;Save the size of the data gotten.
- mvi a,'D' ;Set the state to data send.
- sta state
- ret
-
- sfil16: cpi 0FFH ;Is it EOF?
- jnz abort ;If not give up.
- mvi a,'Z' ;Set the state to EOF.
- sta state
- ret
-
- sfile2: cpi 'N' ;NAK?
- jnz sfile3 ;Try if error packet.
- call updrtr ;Update the number of retries.
- lda pktnum ;Get the present packet number.
- inr a ;Increment
- ani 3FH ; modulo 64
- mov b,a
- lda argblk ;Get the packet's number.
- cmp b ;Is the packet's number one more than now?
- rnz ;If not go try again.
- jmp sfil14 ;Just as good as a ACK;go to the ACK code.
-
- sfile3: cpi 'E' ;Is it an error packet.
- jnz abort
- call error
- jmp abort
-
- ; copy remote name into packet to send [gnn]
- sfile4: xchg ;[gnn] keep pointer to packet
- lxi h,remnam ;[gnn] set pointer to name
- mov c,a ;[gnn] keep count of length
- mov b,a ;[gnn] and set as loop counter
- sfil41: mov a,m ;[gnn] get a character
- stax d ;[gnn] copy it to packet
- inx h ;[gnn]
- inx d ;[gnn] move pointers
- dcr b ;[gnn]
- mov a,b ;[gnn]
- ora a ;[gnn] done them all?
- jnz sfil41 ;[gnn] repeat until done
- xchg ;[gnn] get final position
- shld datptr ;[gnn] and save it
- jmp sfil13 ;[gnn] now go and send packet
-
- ;
- ; Send data
- ; called by: send
-
- sdata: lda numtry ;Get the number of tries.
- cpi maxtry ;Have we reached the maximum number of tries?
- jm sdata1
- lxi d,erms14
- call error3
- jmp abort ;Change the state to abort.
-
- sdata1: inr a ;Increment it.
- sta numtry ;Save the updated number of tries.
- lxi h, data ;Get a pointer to our data block.
- shld datptr ;Save it.
- lxi h,filbuf ;Pointer to chars to be sent.
- shld cbfptr ;Save position in char buffer.
- mvi b,1 ;First char.
- sdat11: lhld cbfptr
- mov a,m
- inx h
- shld cbfptr ;Save position in char buffer.
- mov c,a ;[jd] preserve character temporarily
- lda quot8 ;[jd] doing eighth-bit quoting?
- ora a ;[jd]
- mov a,c ;[jd] restore char
- jnz sdat4 ;[jd] using eighth-bit quoting, no warning
- lda parity ;[jd] get parity
- cpi parnon ;[jd] none?
- mov a,c ;[jd] restore character
- jz sdat4 ;[jd] no parity, leave char alone
- lda wrn8 ;[jd] look at warning flag
- ora a ;[jd] have we already given the warning?
- jnz sdat5 ;[jd] yes, skip this
- mov a,c ;[jd] restore character...
- ani 80h ;[jd] examine parity
- jz sdat5 ;[jd] no parity, no warning.
- call parwrn ;[jd] ...print warning - parity lost
- mvi a,0ffh ;[jd] remember that we sent the message
- sta wrn8 ;[jd]
- sdat5: mov a,c ;[jd] restore character again
- ani 7fh ;[jd] strip parity so not checksummed
- sdat4: lhld datptr
- mov m,a ;Put the char in the data packet.
- inx h
- shld datptr ;Save position in data packet.
- inr b ;Increment the count.
- lda size ;Get the number of chars in char buffer.
- cmp b ;Have we transfered that many?
- jp sdat11 ;If not get another.
- lda size ;Number of char in char buffer.
- sta argblk+1
- lda pktnum ;Get the packet number.
- sta argblk
- mvi a,'D' ;Data packet.
- call spack ;Send the packet.
- jmp abort ; Failed, abort.
- call rpack ;Get a packet.
- jmp r ; Trashed packet don't change state, retry.
- cpi 'Y' ;ACK?
- jnz sdata2 ;If not try next.
- call compp
- rnz ;If not hold out for the right one.
- lda argblk ;Get the packet number back
- call countp
- lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- xra a
- sta numtry ;Reset the number of tries.
- lda argblk+1 ;Get the data length
- cpi 1 ;Check if only 1 character?
- jnz sdat15 ;If not, just continue
- lda data ;Got one character, get it from data
- cpi 'Z' ;Want to abort entire stream?
- jnz sdat14 ;If not, check for just this file
- sta czseen ;Yes, remember it
- jmp sdat16 ;[MF] and set EOF state
- sdat14: cpi 'X' ;Desire abort of current file?
- jnz sdat15 ;If not, just continue
- sta czseen ;Yes, remember that
- jmp sdat16 ;[MF] and set EOF
- sdat15: lda czseen ;Also get control-Z flag
- ora a ;Check if either given
- jz sdat12 ;If neither given, continue
- sdat16: mvi a,'Z' ;Change state to EOF
- sta state ; . . .
- ret ;And return
-
- sdat12: call gtchr
- jmp sdat13 ;Error go see if its EOF.
- sta size ;Save the size of the data gotten.
- ret
-
- sdat13: cpi 0FFH ;Is it EOF?
- jnz abort ;If not give up.
- mvi a,'Z' ;Set the state to EOF.
- sta state
- ret
-
- sdata2: cpi 'N' ;NAK?
- jnz sdata3 ;See if is an error packet.
- call updrtr ;Update the number of retries.
- lda pktnum ;Get the present packet number.
- inr a ;Increment
- ani 3FH ; modulo 64
- mov b,a
- lda argblk ;Get the packet's number.
- cmp b ;Is the packet's number one more than now?
- rnz ;If not go try again.
- jmp sdat12 ;Just as good as a ACK;go to the ACK code.
-
- sdata3: cpi 'E' ;Is it an error packet.
- jnz abort
- call error
- jmp abort
- ;
- ; Send EOF
- ; called by: send
-
- seof: lda numtry ;Get the number of tries.
- cpi maxtry ;Have we reached the maximum number of tries?
- jm seof1
- lxi d,erms14
- call error3
- jmp abort ;Change the state to abort.
-
- seof1: inr a ;Increment it.
- sta numtry ;Save the updated number of tries.
- lda pktnum ;Get the packet number.
- sta argblk
- xra a
- sta argblk+1 ;No data.
- lda czseen ;Check if C-Z or C-X typed
- ora a ; . . .
- jz seof14 ;If not aborted, just keep going
- mvi a,'D' ;Tell other end to discard packet
- sta data ;Store in data portion
- mvi a,1 ;One character
- sta argblk+1 ;Store the length
- seof14: mvi a,'Z' ;EOF packet.
- call spack ;Send the packet.
- jmp abort ; Failed, abort.
- call rpack ;Get a packet.
- jmp r ; Trashed packet don't change state, retry.
- cpi 'Y' ;ACK?
- jnz seof2 ;If not try next.
- call compp
- rnz ;If not hold out for the right one.
- seof12: call countp
- lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- xra a
- sta numtry ;Reset the number of tries.
- mvi c,closf ;Close the file.
- lxi d,fcb
- call bdos
- ;* Check if successful
- lda czseen ;Desire abort of entire stream?
- cpi 'Z' ;Desire abort of entire stream?
- jz seof13 ;If so, just give up now
- call mfname ;Get the next file.
- jc seof13 ; No more.
- call getfil ;and open it (assume success)
- xra a ;Clear A
- sta czseen ;Since we have not aborted this file
- mvi a,'F' ;Set the state to file send.
- sta state
- ret
-
- seof13: mvi a,'B' ;Set the state to EOT.
- sta state
- ret
-
- seof2: cpi 'N' ;NAK?
- jnz seof3 ;Try and see if its an error packet.
- call updrtr ;Update the number of retries.
- lda pktnum ;Get the present packet number.
- inr a ;Increment
- ani 3FH ; modulo 64
- mov b,a
- lda argblk ;Get the packet's number.
- cmp b ;Is the packet's number one more than now?
- rnz ;If not go try again.
- jmp seof12 ;Just as good as a ACK;go to the ACK code.
-
- seof3: cpi 'E' ;Is it an error packet.
- jnz abort
- call error
- jmp abort
- ;
- ; Send EOT
- ; called by: send
-
- seot: lda numtry ;Get the number of tries.
- cpi maxtry ;Have we reached the maximum number of tries?
- jm seot1
- lxi d,erms14
- call error3
- jmp abort ;Change the state to abort.
-
- seot1: inr a ;Increment it.
- sta numtry ;Save the updated number of tries.
- lda pktnum ;Get the packet number.
- sta argblk
- xra a
- sta argblk+1 ;No data.
- mvi a,'B' ;EOF packet.
- call spack ;Send the packet.
- jmp abort ; Failed, abort.
- call rpack ;Get a packet.
- jmp r ; Trashed packet don't change state, retry.
- cpi 'Y' ;ACK?
- jnz seot2 ;If not try next.
- call compp
- rnz ;If not hold out for the right one.
- seot12: call countp
- lda numtry ;Get the number of tries.
- sta oldtry ;Save it.
- xra a
- sta numtry ;Reset the number of tries.
- mvi a,'C' ;Set the state to file send.
- sta state
- ret
-
- seot2: cpi 'N' ;NAK?
- jnz seot3 ;Is it error.
- call updrtr ;Update the number of retries.
- lda pktnum ;Get the present packet number.
- inr a ;Increment
- ani 3FH ; modulo 64
- mov b,a
- lda argblk ;Get the packet's number.
- cmp b ;Is the packet's number one more than now?
- rnz ;If not go try again.
- jmp seot12 ;Just as good as a ACK;go to the ACK code.
-
- seot3: cpi 'E' ;Is it an error packet.
- jnz abort
- call error
- jmp abort
- ;
- ; This routine sets up the data for init packet (either the
- ; Send_init or ACK packet).
- ; called by: rinit, rfile, sinit
- ;
- ; Called by rinit, rfile and sinit. See what WE want from the other fella
- ;
- ; [11] by OBS - Stripped out all the new capas code etc and reverted
- ; to Good Ol' Basic Kermit again!
- ; Those keen should study the followin gode with care, and remove
- ; or add semicolons as indicated.
- ;
- ; See also SPAR which decodes what comes in. It also decodes bits in
- ; the "capability" fields. (Two CAPAS files allowed from remote
- ; machines, but we will only send one at max.) Note that not all
- ; if any of the capability bits will be used.
- ;
- ; Definitions - init packet (data section only.. rest of header assumed OK)
- ; Byte 0 Maximum length I want to send
- ; 1 The Timeout I want you to use
- ; 2 Number of PAD characters I want tot use (May be null)
- ; 3 The PAD character I want to use (May be Null)
- ; 4 The End-of-Line character I will use (Carriage Return)
- ; 5 The control character Quote Character I will use (#)
- ; 6 The parity bit Quote Character I will use (&)
- ; 7 The Checktype I will use
- ; 8 The repeat prefix I will use (Null, as we cannot to repeats)
- ; 9 Capability Byte 0 (See SPAR for defs)
- ; 10 Capability byte 1 ( --- " --- but we will not send it.)
- ; 11 The number of packets I will send per window (not used)
- ; 12 MAXL1 - Long packet size, ms count
- ; 13 MAXL2 - Long packet size, ls count
- ;
- ;
- ; Enter with HL pointing to the "data" part of the packet.
-
- ;
- ; older part of rpar follows...
- ;
- ;
- rpar: lda rpsiz ;Get the receive packet size.
- adi space ;Add a space to make it printable.
- mov m,a ;Put it in the packet.
- inx h ;Point to the next char.
- lda rtime ;Get the receive packet time out.
- adi space ;Add a space.
- mov m,a ;Put it in the packet.
- inx h
- lda rpad ;Get the number of padding chars.
- adi space
- mov m,a
- inx h
- lda rpadch ;Get the padding char.
- adi 100O ;Uncontrol it.
- ani 7FH
- mov m,a
- inx h
- lda reol ;Get the EOL char.
- adi space
- mov m,a
- inx h
- lda rquote ;Get the quote char.
- mov m,a
- inx h
- mvi m,'Y' ;[jd] we know how to do 8-bit quoting
- lda parity ;[jd]
- cpi parnon ;[jd] parity none?
- jz rpar1 ;[jd] yes, keep going
- lda qbchr ;[jd] no, better request 8-bit quoting
- mov m,a
-
- rpar1:
- inx h ;Advance to next
- lda chktyp ;Get desired block check type
- mov m,a ;Store it
- inx h ;Advance pointer
-
- ; Comment out the next two lines for capas etc. WILL require debugging
- mvi a,8 ; this id the older end for this routine. May be useful.
- ret
-
- ; [11] Rest not needed for now, commented out
- ; [10] (to ret)
- ; New additions to rpar follows...
-
- ; lda rcap1 ; get the first capability byte
- ; ani 3eh ; mask out bit 0, ie only one CAPAS byte
- ; adi space ; tochar it
- ; mov m,a
- ; inx h
- ; mvi m,space ; No windows, ie space to packet
- ; inx h
- ; push h ; we need the HL regs for maths.
- ; lhld rdpkt ; get receive packet length
- ; lxi d,95 ; we want hl div 95 and hl mod 95
- ; call divide ; return with divsion in hl, remainder in de
- ; mov a,l ; two sets of bytes
- ; pop h
- ; adi space ; tochar(maxl1)
- ; mov m,a
- ; inx h
- ; mov a,l
- ; adi space ; tochar(maxl2)
- ; mov m,a
- ;
- ; done all, set databytes = 12 and return
- ; mvi a,12 ; 12 bits of data
- ; ret
-
- ;[11] End of commented out code for rpar
-
-
- ;
- ; This routine reads in all the send_init packet information.
- ; called by: rinit, sinit
-
- ;[11] As for rpar, restore the "old" kermit code for non-capas Kermit.
- ;[10] (to ret at end)
- ;
- ; SPAR - routine to decode parameters received from the remote end
- ;
- ; Called by rinit,sinit
- ;
- ; Entry: a: Number of databytes in packet
- ; hl: Pointer to "data" part of packet
- ;
- ;spar: sta temp4 ; save for a while
- ; ; first clear some variables
- ; lda dspsiz ; get default "send" packet length
- ; sta spktl
- ; lda dstime ; get default time-out
- ; sta stimeo
- ; xra a ; set no pad characters by default
- ; sta spad
- ; lda dspadc ; get the default padding character
- ; sta spadc
- ; mvi a,cr ; default end of line character (CR)
- ; sta seol
- ; mvi a,dsquot ; default quote character
- ; sta squote
- ; mvi a,dsbqut ; default binary quote character
- ; sta qbchr
- ; mvi a,dschkt ; set checktype = 1 for inits
- ; sta inichk
- ; mvi a,space ; no repeat prefixing ( otherwise ~)
- ; sta srept
- ;
- ; Now follows the "capabilities" bits... 5 bits per capas byte.
- ;
- ; Note: Before extracting any data bits, apply unchar() to get the
- ; six ls bits. If bit 0 = 1 the a subsequent capaa byte follows
- ;
- ; Byte0: Bit 0: Set to 1 if there are subsequent CAPAS bytes
- ; 1: (Cap. 5) Set to 1 for long packets. Second byte
- ; AFTER the last capas byte has packet length DIV 95
- ; and Thire byte has length MOD 95
- ; 2: (Cap. 4) Sliding Windows. If used, first byte AFTER
- ; last capas byte has TOCHAR(no. of packets in window)
- ; 3: (Cap. 3) Ability to accept "A" (attribute packets)
- ; 4: (Cap. 2) Reserved
- ; 5: (Cap. 1) Reserved
- ; Byte 2 onward: not used in this implementation. Any capas bytes sent
- ; will be stored, however.
- ;
- ; lda temp4 ; get the number of bytes to test
- ; mov c,a ; to a count register
- ; mov a,m ; get first byte
- ; call decc ; unchar it, and decrement c
- ; sta spsiz ; save a send packet size
- ; jz sparx ; if no more, exit
- ;
- ; mov a,m ; get timout
- ; call decc
- ; sta stime ; save timeout
- ; jz sparx
- ;
- ; mov a,m ; get pad characters
- ; call decc
- ; sta spadc ; save it
- ; jz sparx
- ;
- ; mov a,m ; get pad character count
- ; call decc
- ; sta spad
- ; jz sparx
- ;
- ; mov a,m ; get send EOL
- ; call decc
- ; sta seol
- ; jz sparx
- ;
- ; mov a,m ; get control quote character
- ; call decc
- ; sta squote
- ; jz sparx
- ;
- ; mov a,m ; get binary (parity) quote char
- ; mov b,a ; this time we actually WANT accumulator
- ; cpi space ; are we doing 8th bit quoteing
- ; jz spar1 ; dont know, assume not
- ; cpi 'N' ; definately not?
- ; jz spar1
- ; cpi 'Y' ; definately - use &
- ; jz spar2
- ; sta squote ; else save the new character
- ;spar2: lda parity ; see if we are using the parity bit
- ; cpi parnon ; no parity => no quoting
- ; jz spar3 ; yup, so use the default quote character &
- ;
- ;spar1: xra a ; save not quoting
- ; sta squote
- ;spar3: call decc ; update counters etc
- ; jz sparx
- ;
- ; mov a,m ; get repeat prefixing
- ; call decc
- ; push psw ; save flags
- ; cpi space-32 ; we want it?
- ; jz spar4
- ; sta srept
- ;spar4: pop psw ; restore flags
- ; jz sparx
- ;
- ; lxi d,scapas ; point to start of capability byte(s)
- ; push psw ; must do this...
- ;spar5: pop psw ; cos we restore the spack
- ; mov a,m
- ; call decc ; get scap1 (or n)
- ; sta scap1
- ; push psw
- ; ani 01 ; another byte following?
- ; jnz spar5
- ; pop psw ; see if any other data bytes (Windows etc)
- ; jz sparx
- ;
- ; mov a,m ; get window size
- ; call decc
- ; sta swindo
- ; jz sparx
- ;
- ; mov a,m ; get long packets ms bits
- ; call decc ;
- ; mov d,a ; unchared ms bits-ish
- ; mov a,m
- ; call decc ; ls bits-ish
- ; push h ; and we are doing maths
- ; push b ; and an intermediate result in c
- ; push psw ; we want flags and the ls bits...
- ; mvi b,0
- ; mov c,d ; get ms bits-ish to bc
- ; push b ; get number to hl
- ; pop h
- ; now multipy by 95
- ; dad h ;*2
- ; dad h ;*4
- ; dad h ;*8
- ; dad h ;*16
- ; push h ; *16 to ...
- ; pop d ; ... de
- ; dad h ;*32
- ; dad d ; *(32+16) = *48
- ; dad h ; *96
- ; mov a,l ; *(96-1)
- ; sub c
- ; mov l,a
- ; mov a,0
- ; sbb h
- ; mov h,a
- ; pop psw ; restore ls bitsish
- ; mov e,a
- ; mvi d,0
- ; dad d ; *95 + ls bits. Phew.
- ; shld sdpkt ; save long packet length
- ; pop b
- ; pop h ; restore regs
- ;
- ;sparx: ret ; if here, (assume) no more data to read in
- ;[10] routines required follow
- ;decc: mov a,m ; get data byte
- ; sui space ; unchar it
- ; inx h ; increment input pointer
- ; dcr c ; decrement data counter
- ; ret ; return
- ;[10] end or spar replacement
-
- ;[11] Restore older spar....
- ; Older spar follows...
- spar: sta temp4 ;Save the number of arguments.
- ; Initialize some variables to their required default values, so we use
- ; the right values even if the remote Kermit doesn't send the full packet:
- ; ; we don't do anything with timeout values yet.
- ; ; no default pad count/pad character?
- mvi a,cr ; EOL character = carriage-return
- sta seol
- mvi a,'#' ; quote character = '#'
- sta squote
- mvi a,'&' ; eighth-bit quote character = '&'
- sta qbchr
- mvi a,'1' ; block-check = 1-character-checksum
- sta inichk
- ;
- mov a,m ;Get the max packet size.
- sbi space ;Subtract a space.
- sta spsiz ;Save it.
- lda temp4
- cpi 3 ;Fewer than three pieces?
- rm ;If so we are done.
- inx h
- inx h ;Increment past the time out info.
- mov a,m ;Get the number of padding chars.
- sbi space
- sta spad
- lda temp4
- cpi 4 ;Fewer than four pieces?
- rm ;If so we are done.
- inx h
- mov a,m ;Get the padding char.
- adi 100O ;Re-controlify it.
- ani 7FH
- sta spadch
- lda temp4
- cpi 5 ;Fewer than five pieces?
- rm ;If so we are done.
- inx h
- mov a,m ;Get the EOL char.
- sbi space
- sta seol
- lda temp4
- cpi 6 ;Fewer than six pieces?
- rm ;If so we are done.
- inx h
- mov a,m ;Get the quote char.
- sta squote
- lda temp4 ;Get the amount of data supplied
- cpi 7 ;Have an 8-bit quote?
- rm ;If not there, all done
- inx h ;Yes, get the character
- mvi a,0 ;[jd]
- sta quot8 ;[jd] assume not quoting
- mov a,m ;Get the supplied character
- cpi 'N' ;[jd] No?
- jz spar1 ;[jd] then don't try to do it
- cpi space ;[jd] maybe they don't know about it...
- jz spar1 ;[jd] then don't try to do it.
- cpi 'Y' ;[jd] Yes?
- jnz spar2 ;[jd] if not 'Y', assume it's a quote char.
- lda parity ;[jd] using parity?
- cpi parnon ;[jd] no, don't need quoting...
- jz spar1 ;[jd]
- mvi a,0ffh ;[jd] else turn on...
- sta quot8 ;[jd] ...quote flag
- jmp spar1
-
- ;[11] Note: If capas etc required, beware of the next two lables, as these
- ; are used elswhere.
-
- spar2: sta qbchr ;[jd] use their quote char (should validate)
- mvi a,0ffh
- sta quot8 ;[jd] turn quote flag and fall thru...
-
- spar1: lda temp4 ;Determine if block check type given
- cpi 8 ;Is the field there?
- rm ;If not, all done
- inx h ;Point to the character
- mov a,m ;Get the value
- mov b,a ;Copy value
- lda chktyp ;Get our type
- cmp b ;Is it our desired type?
- rnz ; If not, use default (1-character-checksum)
- sta inichk ; Match, store as type to use after init
- ret ; and return
- ;[10] end of replacement
- ;[11] end of replacement of replacement (ie back to original code)
- ;
-
- ; Copy characters from packet to disk (or screen)
- ; called by: rdata
-
- ptchr: sta temp1 ;Save the size.
- lda remtxt ;[MF]Get remote command flag
- ora a ;[MF]Remote command in progress?
- jnz ptchr0 ;[MF]Yes, don't check for file collisions
- lda flwflg ;[MF]Get File Warning (Set Collision) flag
- cpi 3 ;[MF]SET COLLISION DISCARD?
- jnz ptchr0 ;[MF]No
- lda dscflg ;[MF]Yes, get "discard" flag
- ora a ;[MF]Discarding file?
- jz ptchr0 ;[MF]No
- mvi a,'X' ;[MF]Yes, simulate a user rejection
- sta czseen ;[MF]...
- jmp rskp ;[MF]and pretend success
- ptchr0: ;[MF]
- lxi h,data ;Beginning of received packet data.
- shld outpnt ;Remember where we are.
- lda rquote
- mov b,a ;Keep the quote char in b.
- mvi c,0 ;[jd] assume no 8-bit quote char
- lda quot8 ;[jd] doing 8-bit quoting?
- ora a
- jz ptchr1 ;[jd] no, keep going
- lda qbchr ;[jd] else get 8-bit quote char
- mov c,a ;[jd] keep this in c
- ptchr1: lxi h,temp1
- dcr m ;Decrement # of chars in packet.
- jm rskp ;Return successfully if done.
- lda remtxt ; to screen only?
- ana a
- jnz ptchr2 ; dont do any disk stuff
- lxi h,chrcnt ;Number of chars remaining in dma.
- dcr m ;Decrement.
- jp ptchr2 ;Continue if space left.
- call outbuf ;Output it if full.
- jmp ptchr9 ; Error return if disk is full.
- ptchr2: lhld outpnt ;Get position in output buffer.
- mov a,m ;Grab a char.
- inx h
- shld outpnt ;and bump pointer.
- mvi e,0 ;[jd] assume nothing to OR in.
- cmp c ;[jd] is it the binary quote char?
- jnz ptch2a ;[jd] no, keep going
- mvi e,80h ;[jd] include parity bit
- lda temp1
- dcr a
- sta temp1 ;[jd] decrement character count
- mov a,m ;[jd] get next character
- inx h
- shld outpnt
- ptch2a: cmp b ;Is it the quote char?
- jnz ptchr3 ;[jd] changed to ptchr3 so includes parity
- mov a,m ;Get the quoted character
- inx h
- shld outpnt ;and bump pointer.
- lxi h,temp1
- dcr m ;Decrement # of chars in packet.
- mov d,a ;Save the char.
- ani 80H ;Turn off all but the parity bit.
- ora e ;[jd] let parity come from either (???)
- mov e,a ;Save the parity bit.
- mov a,d ;Get the char.
- ani 7FH ;Turn off the parity bit.
- cmp b ;Is it the quote char?
- jz ptchr3 ;If so just go write it out.
- cmp c ;[jd] maybe it's the 8-bit prefix character?
- jz ptchr3 ;[jd] then don't controllify.
- mov a,d ;Get the char.
- adi 40H ;Make the character a control char again.
- ani 7FH ;Modulo 128.
- ptchr3: ora e ;Or in the parity bit.
- sta temp3 ; save for a while
- lda remtxt ; to screen or disk?
- ana a
- lda temp3
- jz ptch31 ; to disk
- push h
- push d
- push b
- mov e,a ; to display
- mvi c,dconio
- call bdos
- pop b
- pop d
- pop h
- jmp ptchr1 ; continue
-
- ptch31: lhld bufpnt ;Destination buffer.
- mov m,a ;Store it.
- inx h
- shld bufpnt ;Update the pointer
- jmp ptchr1 ;and loop to next char.
-
- ptchr9: lxi d,erms11 ; "?Disk full"
- push d ;[MF] Save pointer
- call error3 ; put it on the error line
- pop d ;[MF] Restore pointer
- lxi h,data ;[MF] Where to put the message for "e" packet
- lda argblk ;[MF] Get packet-number
- call countp ;[MF]Increment it
- sta argblk ;[MF] as packet to send
- xra a ;[MF] Zero length of packet data
- sta temp1 ;[MF] ...
- ptch9a: ldax d ;[MF] Get a character to copy
- cpi cr ;[MF] No more to copy?
- jz ptch9b ;[MF] Yes, we can send the packet
- mov m,a ;[MF] No, copy the character
- inx d ;[MF] and increment source/dest pointers
- inx h ;[MF] ...
- lda temp1 ;[MF] Get character count
- inr a ;[MF] and increment it
- sta temp1 ;[MF] ...
- jmp ptch9a ;[MF] Copy entire error message
- ptch9b: mvi m,0 ;[MF]Put in a zero
- lda temp1 ;[MF] Get number of characters in the message
- sta argblk+1 ;[MF] and store as number of packet data chars
- mvi a,'E' ;[MF] Make it an error packet
- call spack ;[MF] Send the error packet
- nop ;[MF] Don't really care if
- nop ;[MF] the send fails since we're
- nop ;[MF] bombing off anyway
- ret ; take error return.
- ;
- ; Fill a data packet from file
- ; called by: sfile, sdata
-
- gtchr: lda squote ;Get the quote char.
- mov c,a ;Keep quote char in c.
- lda curchk ;Get current block check type
- sui '1' ;Get the extra overhead
- mov b,a ;Get a copy
- lda spsiz ;Get the maximum packet size.
- sui 5 ;Subtract the overhead.
- sub b ;Determine max packet length
- sta temp1 ;This is the number of chars we are to get.
- lxi h,filbuf ;Where to put the data.
- shld cbfptr ;Remember where we are.
- mvi b,0 ;No chars.
- gtchr1: lda temp1
- dcr a ;Decrement the number of chars left.
- jp gtchr2 ;Go on if there is more than one left.
- mov a,b ;Return the count in A.
- jmp rskp
-
- gtchr2: sta temp1
- lda chrcnt ;Space left in the DMA.
- dcr a
- ;* Can improve order here.
- jm gtchr3
- sta chrcnt
- jmp gtchr4
-
- gtchr3: call inbuf ;Get another buffer full.
- jmp gtch30 ; If no more return what we got.
- jmp gtchr4 ;If we got some, proceed.
-
- gtch30: mov a,b ;Return the count in A.
- ora a ;Get any chars?
- jnz rskp ;If so return them.
- jmp gtceof ;If not, say we found the end of the file.
-
- gtchr4: lhld bufpnt ;Position in DMA.
- mov a,m ;Get a char from the file.
- inx h
- shld bufpnt
- mov d,a ;Save the char.
- ani 80H ;Turn off all but parity.
- mov e,a ;Save the parity bit.
- jz gtch4a ;[jd] no parity, skip this check...
- lda quot8 ;[jd] doing eighth-bit quoting?
- ora a
- jz gtch4a ;[jd] no, just proceed normally
- lda temp1 ;[jd] get space remaining
- cpi 2 ;[jd] 3 chrs left (one cnted already)?
- jm gtchr9 ;[jd] no, skip this
- dcr a ;[jd] decrement space remaining
- sta temp1 ;[jd] put back.
- lhld cbfptr ;[jd] Position in character buffer.
- lda qbchr ;[jd] get quote character
- mov m,a ;]jd] Put the quote char in the buffer.
- inx h ;[jd] increment destination buffer pointer
- shld cbfptr ;[jd] store the pointer back
- inr b ;[jd] Increment the char count.
- mvi e,0 ;[jd] no parity bit to OR in.
- ;[jd] fall thru...
-
- gtch4a: mov a,d ;Restore the char.
- ani 7FH ;Turn off the parity.
- mov d,a ;[jd] save here for later...
- cpi space ;Compare to a space.
- jm gtchr5 ;If less then its a control char, handle it.
- cpi del ;Is the char a delete?
- jz gtchr5 ;Go quote it.
- lda quot8 ; Are we doing 8th-bit quoting?
- ora a
- jz gtch4c ; if not, skip this test and restore character.
- lda qbchr ; get 8th-bit quote character
- cmp d ; same as current character?
- jz gtch4b ; yes, have to quote it...
- gtch4c: mov a,d ; no. get character back again.
- cmp c ;Is it the quote char?
- jnz gtchr8 ;If not proceed.
- gtch4b: lxi h,temp1 ;[jd] point to char count
- dcr m ;[jd] decrement (know room for at least one)
- lhld cbfptr ;Position in character buffer.
- mov m,c ;Put the (quote) char in the buffer.
- inx h
- shld cbfptr
- inr b ;Increment the char count.
- mov a,d ;[jd] restore character again
- jmp gtchr8
-
- gtchr5:
- ;[gnn] ignore parity for checking
- ; ora e ;Turn on the parity bit.
-
- cpi ('Z'-100O) ;Is it a ^Z?
- jnz gtchr7 ;If not just proceed.
- lda cpmflg ;Was the file created by CPM...
- cpi 1 ;in ASCII-mode ?
- jz gtch52 ;Control-Z stops text
- cpi 2 ;in BINARY mode?
- jz gtchr6 ;Yes, pass the ^Z
- ;At this point file-mode is DEFAULT.
- ;If the rest of the record is filled with ^Zs, we're at EOF, otherwise
- ;its a regular character.
- lhld bufpnt ;since CHRCNT is ZERO at EOF-time
- lda chrcnt ;(set by INBUF5 B.G.E)
- mov d,a ;Get the number of chars left in the DMA.
- gtch51: dcr d
- mov a,d
- jp gtch53 ;Any chars left?
- gtch52: xra a ;If not, get a zero.
- sta chrcnt ;Say no more chars in buffer.
- mov a,b ;Return the count in A.
- jmp rskp
-
- ;Scan rest of buffer for non ^Z -- If we find a non ^Z, fall into gtchr6.
- ;If we get to the end of the buffer before finding a non ^Z, fall into gtch52.
- gtch53: mov a,m ;Get the next char.
- inx h ;Move the pointer.
- cpi ('Z'-100O) ;Is it a ^Z?
- jz gtch51 ;If so see if the rest are.
-
- gtchr6: mvi a,('Z'-100O) ;Restore the ^Z.
- gtchr7: sta temp2 ;Save the char.
- lxi h,temp1 ;Point to the char total remaining.
- dcr m ;Decrement it.
- lhld cbfptr ;Position in character buffer.
- mov m,c ;Put the quote in the buffer.
- inx h
- shld cbfptr
- inr b ;Increment the char count.
- lda temp2 ;Get the control char back.
- adi 40H ;Make the non-control.
- ani 7fH ;Modulo 200 octal.
- gtchr8: lhld cbfptr ;Position in character buffer.
- ora e ;Or in the parity bit.
- mov m,a ;Put the char in the buffer.
- inx h
- shld cbfptr
- inr b ;Increment the char count.
- jmp gtchr1 ;Go around again.
-
- gtchr9: ;[jd] not enough room left in buffer...
- lhld bufpnt
- dcx h
- shld bufpnt ;[jd] back up over last character
- lxi h,chrcnt ;[jd] point to character count
- inr m ;[jd] increment it
- mov a,b ;[jd] count of chars transferred
- jmp rskp ;[jd] return it
-
- gtceof: mvi a,0FFH ;Get a minus one.
- ret
- ;
-
- ; Little code to allow some expansion of code without changing
- ; every futher address, only up to the end of this file.
- ; TO BE REMOVED FRO RELEASE!
-
- ; org ($+100h) AND 0FF00H
-
- IF lasm
- LINK CPSPK2 ;[obs] Link to part two of the packet file
- ENDIF ;lasm
-